package com.meida.module.admin.provider.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.meida.common.base.handler.UserDeptAssignHandler;
import com.meida.common.base.service.BaseAdminUserService;
import com.meida.common.constants.CommonConstants;
import com.meida.common.enums.StateEnum;
import com.meida.common.mybatis.base.service.impl.BaseServiceImpl;
import com.meida.common.base.entity.EntityMap;
import com.meida.common.mybatis.model.PageParams;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaDelete;
import com.meida.common.mybatis.query.CriteriaQuery;
import com.meida.common.mybatis.query.CriteriaSave;
import com.meida.common.mybatis.query.CriteriaUpdate;
import com.meida.common.security.OpenAuthority;
import com.meida.common.security.OpenHelper;
import com.meida.common.security.SecurityConstants;
import com.meida.common.utils.ApiAssert;
import com.meida.common.base.utils.FlymeUtils;
import com.meida.module.admin.client.entity.*;
import com.meida.module.admin.client.model.UserInfo;
import com.meida.module.admin.provider.mapper.BaseRoleUserMapper;
import com.meida.module.admin.provider.mapper.BaseUserCompanyMapper;
import com.meida.module.admin.provider.mapper.BaseUserDeptMapper;
import com.meida.module.admin.provider.mapper.BaseUserMapper;
import com.meida.module.admin.provider.service.BaseAccountService;
import com.meida.module.admin.provider.service.BaseAuthorityService;
import com.meida.module.admin.provider.service.BaseRoleService;
import com.meida.module.admin.provider.service.BaseUserService;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * @author: zyf
 * @date: 2018/10/24 16:33
 * @description:
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class BaseUserServiceImpl extends BaseServiceImpl<BaseUserMapper, BaseUser> implements BaseUserService, BaseAdminUserService {

    @Resource
    private BaseUserMapper baseUserMapper;
    @Resource
    private BaseRoleService roleService;

    @Resource
    private BaseRoleUserMapper roleUserMapper;
    @Resource
    private AutowireCapableBeanFactory spring;
    @Resource
    private BaseAuthorityService baseAuthorityService;

    @Resource
    private BaseRoleService baseRoleService;

    @Resource
    private BaseUserCompanyMapper baseUserCompanyMapper;

    @Resource
    private BaseUserDeptMapper baseUserDeptMapper;

    @Resource
    private BaseAccountService baseAccountService;

    @Autowired(required = false)
    private UserDeptAssignHandler userDeptAssignHandler;


    @Override
    public ResultBody beforeAdd(CriteriaSave cs, BaseUser baseUser, EntityMap extra) {
        String userName = baseUser.getUserName();
        if (getUserByUsername(userName) != null) {
            ApiAssert.failure("用户名:" + userName + "已注册");
        }
        Integer superAdmin = OpenHelper.getUser().getSuperAdmin();
        if (CommonConstants.INT_0.equals(superAdmin)) {
            Long organizationId = OpenHelper.getOrganizationId();
            if (FlymeUtils.isNotEmpty(organizationId)) {
                baseUser.setOrganizationId(organizationId);
            }
        }
        return super.beforeAdd(cs, baseUser, extra);
    }


    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<BaseUser> cq, BaseUser baseUser, EntityMap requestMap) {
        PageParams pageParams = cq.getPageParams();
        BaseUser query = cq.getEntity(BaseUser.class);
        cq.lambda()
                .eq(FlymeUtils.isNotEmpty(query.getUserId()), BaseUser::getUserId, query.getUserId())
                .eq(FlymeUtils.isNotEmpty(query.getUserType()), BaseUser::getUserType, query.getUserType())
                .eq(FlymeUtils.isNotEmpty(query.getUserName()), BaseUser::getUserName, query.getUserName())
                .like(FlymeUtils.isNotEmpty(query.getNickName()), BaseUser::getNickName, query.getNickName())
                .eq(FlymeUtils.isNotEmpty(query.getMobile()), BaseUser::getMobile, query.getMobile())
                .ge(FlymeUtils.isNotEmpty(pageParams.getBeginDate()), BaseUser::getRegisterTime, pageParams.getBeginDate())
                .le(FlymeUtils.isNotEmpty(pageParams.getEndDate()), BaseUser::getRegisterTime, pageParams.getEndDate())
                .eq(FlymeUtils.isNotEmpty(query.getStatus()), BaseUser::getStatus, query.getStatus());
        cq.orderByDesc("createTime");
        return super.beforePageList(cq, baseUser, requestMap);
    }




    /**
     * 查询列表
     *
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public List<BaseUser> findAllList() {
        List<BaseUser> list = baseUserMapper.selectList(new QueryWrapper<>());
        return list;
    }

    /**
     * 依据系统用户Id查询系统用户信息
     *
     * @param userId
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public BaseUser getUserById(Long userId) {
        return baseUserMapper.selectById(userId);
    }


    /**
     * 根据用户ID获取用户信息和权限
     *
     * @param userId
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public UserInfo getUserWithAuthoritiesById(Long userId) {
        // 用户权限列表
        List<OpenAuthority> authorities = Lists.newArrayList();
        // 用户角色列表
        List<Map> roles = Lists.newArrayList();
        List<BaseRole> rolesList = roleService.getUserRoles(userId);
        Integer superAdmin = 0;
        if (rolesList != null) {
            for (BaseRole role : rolesList) {
                String roleCode = role.getRoleCode();
                Map roleMap = Maps.newHashMap();
                roleMap.put("roleId", role.getRoleId());
                roleMap.put("roleCode", role.getRoleCode());
                roleMap.put("roleName", role.getRoleName());
                // 用户角色详情
                roles.add(roleMap);
                // 加入角色标识
                OpenAuthority authority = new OpenAuthority(role.getRoleId().toString(), SecurityConstants.AUTHORITY_PREFIX_ROLE + role.getRoleCode(), null, "role");
                authorities.add(authority);
                if (roleCode.equals("superadmin") || roleCode.equals("admin")) {
                    superAdmin = 1;
                }
            }
        }

        //查询系统用户资料
        BaseUser baseUser = getUserById(userId);

        // 加入用户权限
        List<OpenAuthority> userGrantedAuthority = baseAuthorityService.findAuthorityByUser(userId, CommonConstants.ROOT.equals(baseUser.getUserName()));
        if (userGrantedAuthority != null && userGrantedAuthority.size() > 0) {
            authorities.addAll(userGrantedAuthority);
        }
        UserInfo userProfile = new UserInfo();
        BeanUtils.copyProperties(baseUser, userProfile);
        userProfile.setSuperAdmin(superAdmin);
        //设置用户资料,权限信息
        userProfile.setAuthorities(authorities);
        userProfile.setRoles(roles);
        return userProfile;
    }


    /**
     * 依据登录名查询系统用户信息
     *
     * @param username
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public BaseUser getUserByUsername(String username) {
        QueryWrapper<BaseUser> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(BaseUser::getUserName, username);
        BaseUser saved = baseUserMapper.selectOne(queryWrapper);
        return saved;
    }

    /**
     * 设置用户状态
     *
     * @param userId
     * @return
     */
    @Override
    public ResultBody setStatus(Long userId) {
        ResultBody resultBody = new ResultBody();
        BaseUser user = baseUserMapper.selectById(userId);
        Integer stateEnum = user.getStatus();
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.eq("userId", userId);
        if (stateEnum.equals(StateEnum.ENABLE.getCode())) {
            cu.set(true, "status", StateEnum.DISABLE.getCode());
            resultBody.setMsg(StateEnum.DISABLE.getName() + "成功").data(false);
        } else {
            cu.set(true, "status", StateEnum.ENABLE.getCode());
            resultBody.setMsg(StateEnum.ENABLE.getName() + "成功").data(true);
        }
        update(cu);
        return resultBody;

    }

    @Override
    public ResultBody deleteUser(String accountName) {
        BaseAccount baseAccount = baseAccountService.getAccount(accountName);
        if (FlymeUtils.isNotEmpty(baseAccount)) {
            Long userId = baseAccount.getUserId();
            if (FlymeUtils.isNotEmpty(userId)) {
                baseRoleService.removeUserRoles(userId);
                baseAccountService.removeAccount(userId);
                removeById(userId);
            }
        }
        return ResultBody.ok();
    }

    /**
     * 移除企业所有组员
     *
     * @param userId
     * @return
     */
    @Override
    public void removeUserCompnay(Long userId) {
        QueryWrapper<BaseUserCompany> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(BaseUserCompany::getUserId, userId);
        baseUserCompanyMapper.delete(queryWrapper);
    }

    /**
     * 移除部门所有组员
     *
     * @param userId
     * @return
     */
    private void removeUserDept(Long userId) {
        QueryWrapper<BaseUserDept> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(BaseUserDept::getUserId, userId);
        baseUserDeptMapper.delete(queryWrapper);
    }

    /**
     * 用户分配企业
     *
     * @param userId
     * @param companyIds
     */
    @Override
    public void saveUserCompanys(Long userId, String... companyIds) {
        ApiAssert.isNotEmpty("用户ID不能为空", userId);
        // 先清空,在添加
        removeUserCompnay(userId);
        if (FlymeUtils.isNotEmpty(companyIds)) {
            for (String companyId : companyIds) {
                BaseUserCompany userCompany = new BaseUserCompany();
                userCompany.setUserId(userId);
                userCompany.setCompanyId(Long.parseLong(companyId));
                baseUserCompanyMapper.insert(userCompany);
            }

        }
    }

    /**
     * 用户分配部门
     *
     * @param userId
     * @param deptIds
     */
    @Override
    public void saveUserDepts(Long userId, String... deptIds) {
        ApiAssert.isNotEmpty("用户ID不能为空", userId);
        // 先清空,在添加
        removeUserDept(userId);
        if (FlymeUtils.isNotEmpty(deptIds)) {
            for (String deptId : deptIds) {
                BaseUserDept userDept = new BaseUserDept();
                userDept.setUserId(userId);
                userDept.setDeptId(Long.parseLong(deptId));
                baseUserDeptMapper.insert(userDept);
            }

        }
    }

    /**
     * 获取分配部门数据
     *
     * @param userId
     * @param organizationId
     * @return
     */
    @Override
    public ResultBody getAuthDeptList(Long userId, Long organizationId) {
        EntityMap map = new EntityMap();
        if (FlymeUtils.isNotEmpty(userDeptAssignHandler)) {
            map = userDeptAssignHandler.getAuthDeptList(userId, organizationId);
            List<Long> deptIds = baseUserDeptMapper.selectUserDeptIds(userId);
            map.put("deptIds",deptIds);
        }
        return ResultBody.ok(map);
    }

    @Override
    public ResultBody beforeDelete(CriteriaDelete<BaseUser> cd) {
        Long userId = OpenHelper.getUserId();
        Long[] userIds = cd.getIds();
        if (FlymeUtils.contains(userIds, userId)) {
            return ResultBody.failed("禁止删除当前用户");
        }
        return super.beforeDelete(cd);
    }

    @Override
    public ResultBody afterDelete(CriteriaDelete cd, Long[] ids) {
        if (FlymeUtils.isNotEmpty(ids)) {
            baseRoleService.removeUserRoles(ids);
            baseAccountService.removeAccount(ids);
        }
        return ResultBody.ok();
    }

    @Override
    public Boolean deleteByCompanyId(Long companyId) {
        CriteriaQuery cq = new CriteriaQuery(BaseUser.class);
        cq.eq(true, "companyId", companyId);
        List<BaseUser> userList = baseUserMapper.selectList(cq);
        if (FlymeUtils.isNotEmpty(userList)) {
            for (BaseUser baseUser : userList) {
                baseRoleService.removeUserRoles(baseUser.getUserId());
                baseAccountService.removeAccount(baseUser.getUserId());
                removeById(baseUser.getUserId());
            }
        }
        return true;
    }
    @Override
    public List<Long> selectUserIdByRoleCode(String roleCode, Long companyId){
        return roleUserMapper.selectUserIdByRoleCode(roleCode,companyId);
    }
}
